package com.wskj.workbench.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.aliyun.dypnsapi20170525.Client;
import com.aliyun.dypnsapi20170525.models.GetMobileRequest;
import com.aliyun.dypnsapi20170525.models.GetMobileResponse;
import com.aliyun.dypnsapi20170525.models.VerifyMobileRequest;
import com.aliyun.dypnsapi20170525.models.VerifyMobileResponse;
import com.aliyun.oss.ClientException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import com.wskj.common.constant.Constants;
import com.wskj.common.constant.RedisConstants;
import com.wskj.common.core.domain.AjaxResult;
import com.wskj.common.core.domain.entity.SysUser;
import com.wskj.common.core.domain.model.LoginUser;
import com.wskj.common.core.mybatisplus.core.ServicePlusImpl;
import com.wskj.common.exception.CustomException;
import com.wskj.common.utils.ali.AliLoginUtils;
import com.wskj.common.utils.ali.DescribeFaceVerify;
import com.wskj.common.utils.ali.InitFaceVerify;
import com.wskj.common.utils.ali.MaterialInfo;
import com.wskj.common.utils.common.*;
import com.wskj.common.utils.wx.WechatUtils;
import com.wskj.system.domain.SysCommon;
import com.wskj.system.domain.SysConfig;
import com.wskj.system.mapper.SysUserMapper;
import com.wskj.system.service.ISysCommonService;
import com.wskj.system.service.ISysConfigService;
import com.wskj.system.service.ISysUserService;
import com.wskj.workbench.bo.app.AppUserBindWxOrAliBo;
import com.wskj.workbench.bo.app.AppUserInfoEditBo;
import com.wskj.workbench.component.TokenService;
import com.wskj.workbench.domain.TbUserJoinOrder;
import com.wskj.workbench.enums.SysUserLoginTypeEnum;
import com.wskj.workbench.enums.SysUserStatusEnum;
import com.wskj.workbench.enums.SysUserUserTypeEnum;
import com.wskj.workbench.enums.UserJoinOrderOrderStatusEnum;
import com.wskj.workbench.param.MetaInfoParam;
import com.wskj.workbench.param.RealNameParam;
import com.wskj.workbench.service.ISysUserExtendService;
import com.wskj.workbench.service.ITbUserJoinOrderService;
import com.wskj.workbench.vo.app.AppUserLoginVo;
import com.wskj.workbench.vo.app.AppWxLoginVo;
import com.wskj.workbench.vo.app.AppWxUserInfoVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import weixin.popular.util.JsonUtil;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;


/**
 * 用户扩展 业务层处理
 *
 * @author ruoyi
 */
@Slf4j
@Service
@AllArgsConstructor
public class SysUserExtendServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser> implements ISysUserExtendService {

    private final TokenService tokenService;
    private final StringRedisTemplate stringRedisTemplate;
    private final StringRedisTemplate redisTemplate;
    private final ISysUserService iSysUserService;

    private final ISysConfigService configService;
    private final ISysCommonService iSysCommonService;

    private final ITbUserJoinOrderService userJoinOrderService;

    private final ISysConfigService sysConfigService;

    @Override
    public AjaxResult login(String phoneNumber, String password) {

        TbUserJoinOrder tbUserJoinOrder = userJoinOrderService.getOne(Wrappers.lambdaQuery(TbUserJoinOrder.class)
                .eq(TbUserJoinOrder::getPhoneNumber, phoneNumber).orderByDesc(TbUserJoinOrder::getCreateTime)
                .last("limit 1"));

        AssertUtils.isTrue(ObjectUtil.isNotEmpty(tbUserJoinOrder), "此账户未注册");


        long countNumber = userJoinOrderService.count(Wrappers.lambdaQuery(TbUserJoinOrder.class).eq(TbUserJoinOrder::getPhoneNumber, phoneNumber)
                .in(TbUserJoinOrder::getOrderStatus,
                        UserJoinOrderOrderStatusEnum.YIZHIFU.getValue(), UserJoinOrderOrderStatusEnum.SHENHETONGGUO.getValue(),
                        UserJoinOrderOrderStatusEnum.SHENHEBUTONGGUO.getValue()));


        if (countNumber == 0) {
            return AjaxResult.error(501, "申请单未支付");
        }

        if (tbUserJoinOrder.getOrderStatus().equals(UserJoinOrderOrderStatusEnum.YIZHIFU.getValue())) {
            return AjaxResult.error(502, "审核中,请耐心等待");
        }

        if (tbUserJoinOrder.getOrderStatus().equals(UserJoinOrderOrderStatusEnum.SHENHEBUTONGGUO.getValue())) {
            return AjaxResult.error(503, tbUserJoinOrder.getReviewReason());
        }


        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(SysUser::getPhoneNumber, phoneNumber);
        List<SysUser> sysUserList = this.getBaseMapper().selectList(lambdaQueryWrapper);
        AssertUtils.isTrue(CollectionUtils.isNotEmpty(sysUserList), "此账户未注册");
        AtomicReference<Boolean> statusNormal = new AtomicReference<>(false);
        AtomicReference<Boolean> statusStop = new AtomicReference<>(false);
        AtomicReference<Boolean> statusLogoff = new AtomicReference<>(false);
        AtomicReference<SysUser> sysUserAtomic = new AtomicReference<>();
        sysUserList.forEach(s -> {
            if (SysUserStatusEnum.NORMAL.getValue().equals(s.getStatus())) {
                sysUserAtomic.set(s);
                statusNormal.set(Boolean.TRUE);
            } else if (SysUserStatusEnum.STOP.getValue().equals(s.getStatus())) {
                statusStop.set(Boolean.TRUE);
            } else if (SysUserStatusEnum.LOGOFF.getValue().equals(s.getStatus())) {
                statusLogoff.set(Boolean.TRUE);
            }
        });
        if (!statusNormal.get() && statusStop.get()) {
            AssertUtils.isFalse(Boolean.TRUE, "该账号已被停用，请联系管理员");
        }
        if (!statusNormal.get() && !statusStop.get()) {
            AssertUtils.isFalse(Boolean.TRUE, "该账号已被注销，请联系管理员");
        }
        SysUser sysUser = sysUserAtomic.get();
        // 验证密码是否正确
        boolean ifSure;
        String shifouqiyon = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getConfigKey, "sfqy_wanneng_password")).getConfigValue();
        if (shifouqiyon.equals("1")) {
            // 先判断原来密码是否能匹配住
            ifSure = SecurityUtils.matchesPassword(password, sysUser.getPassword());
            // 如果原来的匹配不住 则判断是不是万能密码
            if (!ifSure) {
                // 如果万能密码也匹配不住 则密码错误
                String wannnegPassword = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getConfigKey, "wannneg_password")).getConfigValue();
                if (wannnegPassword.equals(password)) {
                    ifSure = true;
                } else {
                    ifSure = false;
                }
            }

        } else {
            ifSure = SecurityUtils.matchesPassword(password, sysUser.getPassword());
        }

        AssertUtils.isTrue(ifSure, "密码不正确");
        // 生成token
        LoginUser loginUser = new LoginUser();
        loginUser.setUser(sysUser);
        // 访问端
        loginUser.setPlatform(2);
        String token = tokenService.createToken(loginUser);
        AppUserLoginVo appUserLoginVo = new AppUserLoginVo();
        appUserLoginVo.setToken(token);
        appUserLoginVo.setUserId(sysUser.getUserId());
        appUserLoginVo.setIfBindPhone(Boolean.TRUE);
        appUserLoginVo.setUserType(sysUser.getUserType());
        return AjaxResult.success("登录成功", appUserLoginVo);
    }

    @Override
    public AjaxResult smsLogin(String phoneNumber, String veryCode) {
        // 验证手机号
        this.validateVeryCode(phoneNumber, veryCode);
        // 查询条件
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(SysUser::getUserName, phoneNumber);
        List<SysUser> sysUserList = this.getBaseMapper().selectList(lambdaQueryWrapper);
        AssertUtils.isTrue(CollectionUtils.isNotEmpty(sysUserList), "此账户未注册");
        AtomicReference<Boolean> statusNormal = new AtomicReference<>(false);
        AtomicReference<Boolean> statusStop = new AtomicReference<>(false);
        AtomicReference<Boolean> statusLogoff = new AtomicReference<>(false);
        AtomicReference<SysUser> sysUserAtomic = new AtomicReference<>();
        sysUserList.forEach(s -> {
            if (SysUserStatusEnum.NORMAL.getValue().equals(s.getStatus())) {
                sysUserAtomic.set(s);
                statusNormal.set(Boolean.TRUE);
            } else if (SysUserStatusEnum.STOP.getValue().equals(s.getStatus())) {
                statusStop.set(Boolean.TRUE);
            } else if (SysUserStatusEnum.LOGOFF.getValue().equals(s.getStatus())) {
                statusLogoff.set(Boolean.TRUE);
            }
        });
        if (!statusNormal.get() && statusStop.get()) {
            AssertUtils.isFalse(Boolean.TRUE, "该账号已被停用，请联系管理员");
        }
        if (!statusNormal.get() && !statusStop.get()) {
            AssertUtils.isFalse(Boolean.TRUE, "该账号已被注销，请联系管理员");
        }
        SysUser sysUser = sysUserAtomic.get();
        // 生成token
        LoginUser loginUser = new LoginUser();
        loginUser.setUser(sysUser);
        // 访问端
        loginUser.setPlatform(2);
        String token = tokenService.createToken(loginUser);
        AppUserLoginVo appUserLoginVo = new AppUserLoginVo();
        appUserLoginVo.setUserId(sysUser.getUserId());
        appUserLoginVo.setIfBindPhone(Boolean.TRUE);
        appUserLoginVo.setUserType(sysUser.getUserType());
        appUserLoginVo.setToken(token);
        return AjaxResult.success("登录成功", appUserLoginVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult<AppUserLoginVo> quickLogin(String uid, String loginType) {
        // 查询条件
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(SysUser::getUserType, SysUserUserTypeEnum.GENERAL_USER.getValue());
        // QQ
        lambdaQueryWrapper.eq(SysUserLoginTypeEnum.QQ_UID.getValue().equals(loginType), SysUser::getQqUid, uid);
        // 微信
        lambdaQueryWrapper.eq(SysUserLoginTypeEnum.WX_UID.getValue().equals(loginType), SysUser::getWxUid, uid);
        // 支付宝
        lambdaQueryWrapper.eq(SysUserLoginTypeEnum.ALIPAY_UID.getValue().equals(loginType), SysUser::getAlipayUid, uid);
        // 苹果
        lambdaQueryWrapper.eq(SysUserLoginTypeEnum.IPHONE_UID.getValue().equals(loginType), SysUser::getIphoneUid, uid);
        List<SysUser> sysUserList = this.getBaseMapper().selectList(lambdaQueryWrapper);
        // 返回值
        AppUserLoginVo appUserLoginVo = new AppUserLoginVo();
        if (CollectionUtils.isNotEmpty(sysUserList)) {
            AtomicReference<Boolean> statusNormal = new AtomicReference<>(false);
            AtomicReference<Boolean> statusStop = new AtomicReference<>(false);
            AtomicReference<Boolean> statusLogoff = new AtomicReference<>(false);
            AtomicReference<SysUser> sysUserAtomic = new AtomicReference<>();
            sysUserList.forEach(s -> {
                if (SysUserStatusEnum.NORMAL.getValue().equals(s.getStatus())) {
                    sysUserAtomic.set(s);
                    statusNormal.set(Boolean.TRUE);
                } else if (SysUserStatusEnum.STOP.getValue().equals(s.getStatus())) {
                    statusStop.set(Boolean.TRUE);
                } else if (SysUserStatusEnum.LOGOFF.getValue().equals(s.getStatus())) {
                    statusLogoff.set(Boolean.TRUE);
                }
            });
            if (!statusNormal.get() && statusStop.get()) {
                AssertUtils.isFalse(Boolean.TRUE, "该账号已被停用，请联系管理员");
            }
            if (!statusNormal.get() && !statusStop.get()) {
                SysUser sysUser = new SysUser();
                // 用户账号
                sysUser.setUserName(uid);
                // 用户类型
                sysUser.setUserType(SysUserUserTypeEnum.GENERAL_USER.getValue());
                // 帐 号状态
                sysUser.setStatus(SysUserStatusEnum.NORMAL.getValue());
                // 唯一标识
                AssertUtils.notNull(SysUserLoginTypeEnum.parse(loginType), "登录类型错误");
                if (SysUserLoginTypeEnum.QQ_UID.getValue().equals(loginType)) {
                    sysUser.setQqUid(uid);
                } else if (SysUserLoginTypeEnum.WX_UID.getValue().equals(loginType)) {
                    sysUser.setWxUid(uid);
                } else if (SysUserLoginTypeEnum.ALIPAY_UID.getValue().equals(loginType)) {
                    sysUser.setAlipayUid(uid);
                } else if (SysUserLoginTypeEnum.IPHONE_UID.getValue().equals(loginType)) {
                    sysUser.setIphoneUid(uid);
                }
                // 个人邀请码
                sysUser.setRecommendCode(CommonUtils.getRecommendCode());
                // 默认支付密码
                String initPayPassword = configService.selectConfigByKey("sys.user.initPayPassword");
                sysUser.setPayPassword(SecurityUtils.encryptPassword(initPayPassword));
                // 保存数据
                this.getBaseMapper().insert(sysUser);
                // 生成令牌
                LoginUser loginUser = new LoginUser();
                loginUser.setUser(sysUser);
                // 访问端
                loginUser.setPlatform(2);
                // 生成token
                String token = tokenService.createToken(loginUser);
                appUserLoginVo.setUserId(sysUser.getUserId());
                appUserLoginVo.setToken(token);
                appUserLoginVo.setUserType(sysUser.getUserType());
                // 是否绑定手机号
                if (StringUtils.isEmpty(sysUser.getPhoneNumber())) {
                    appUserLoginVo.setIfBindPhone(Boolean.FALSE);
                }
                return AjaxResult.success("登录成功", appUserLoginVo);
            }
            SysUser sysUser = sysUserAtomic.get();
            // 生成令牌
            LoginUser loginUser = new LoginUser();
            loginUser.setUser(sysUser);
            // 生成token
            String token = tokenService.createToken(loginUser);
            appUserLoginVo.setUserId(sysUser.getUserId());
            appUserLoginVo.setToken(token);
            // 是否绑定手机号
            if (StringUtils.isEmpty(sysUser.getPhoneNumber())) {
                appUserLoginVo.setIfBindPhone(Boolean.FALSE);
            }
            return AjaxResult.success("登录成功", appUserLoginVo);
        }
        SysUser sysUser = new SysUser();
        // 用户账号
        sysUser.setUserName(uid);
        // 用户类型
        sysUser.setUserType(SysUserUserTypeEnum.GENERAL_USER.getValue());
        // 帐 号状态
        sysUser.setStatus(SysUserStatusEnum.NORMAL.getValue());
        // 唯一标识
        AssertUtils.notNull(SysUserLoginTypeEnum.parse(loginType), "登录类型错误");
        if (SysUserLoginTypeEnum.QQ_UID.getValue().equals(loginType)) {
            sysUser.setQqUid(uid);
        } else if (SysUserLoginTypeEnum.WX_UID.getValue().equals(loginType)) {
            sysUser.setWxUid(uid);
        } else if (SysUserLoginTypeEnum.ALIPAY_UID.getValue().equals(loginType)) {
            sysUser.setAlipayUid(uid);
        } else if (SysUserLoginTypeEnum.IPHONE_UID.getValue().equals(loginType)) {
            sysUser.setIphoneUid(uid);
        }
        // 个人邀请码
        sysUser.setRecommendCode(CommonUtils.getRecommendCode());
        // 默认支付密码
        String initPayPassword = configService.selectConfigByKey("sys.user.initPayPassword");
        sysUser.setPayPassword(SecurityUtils.encryptPassword(initPayPassword));
        // 保存数据
        this.getBaseMapper().insert(sysUser);
        // 生成令牌
        LoginUser loginUser = new LoginUser();
        loginUser.setUser(sysUser);
        // 访问端
        loginUser.setPlatform(2);
        // 生成token
        String token = tokenService.createToken(loginUser);
        appUserLoginVo.setUserId(sysUser.getUserId());
        appUserLoginVo.setToken(token);
        appUserLoginVo.setUserType(sysUser.getUserType());
        // 是否绑定手机号
        if (StringUtils.isEmpty(sysUser.getPhoneNumber())) {
            appUserLoginVo.setIfBindPhone(Boolean.FALSE);
        }
        return AjaxResult.success("登录成功", appUserLoginVo);
    }

    @Override
    public AjaxResult appletLogin(String code, String nickName, String headImage) {
        // 第一步 获取临时登录code
        log.info("获取微信用户基本信息:{}", code);
        // 第二步：通过code换取网页授权access_token 微信小程序APPID  微信小程序秘钥
        String openId = WechatUtils.getOpenid(iSysCommonService.getById(1000002L).getCommonValue(), iSysCommonService.getById(1000003L).getCommonValue(), code);
        AssertUtils.notBlank(openId, "微信授权失败");
        // 查询条件
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper();
        // 微信
        lambdaQueryWrapper.eq(SysUser::getWxUid, openId);
        SysUser sysUser = this.getBaseMapper().selectOne(lambdaQueryWrapper);
        // 返回值
        AppUserLoginVo appUserLoginVo = new AppUserLoginVo();
        if (sysUser != null) {
            // 判断该用户是否被禁用(0=正常,1=停用)
            AssertUtils.isTrue(SysUserStatusEnum.NORMAL.getValue().equals(sysUser.getStatus()), "该账号已被停用，请联系管理员");
            // 用户昵称
            sysUser.setNickName(nickName);
            // 用户头像
            sysUser.setAvatar(headImage);
            // 更新数据
            baseMapper.updateById(sysUser);
            // 生成令牌
            LoginUser loginUser = new LoginUser();
            loginUser.setUser(sysUser);
            // 生成token
            String token = tokenService.createToken(loginUser);
            appUserLoginVo.setToken(token);
            appUserLoginVo.setUserId(sysUser.getUserId());
            // 是否绑定手机号
            if (StringUtils.isEmpty(sysUser.getPhoneNumber())) {
                appUserLoginVo.setIfBindPhone(Boolean.FALSE);
            }
            return AjaxResult.success("登录成功", appUserLoginVo);
        }
        sysUser = new SysUser();
        // 用户账号
        sysUser.setUserName(openId);
        // 用户昵称
        sysUser.setNickName(nickName);
        // 头像
        sysUser.setAvatar(headImage);
        // 用户类型
        sysUser.setUserType(SysUserUserTypeEnum.GENERAL_USER.getValue());
        // 帐号状态
        sysUser.setStatus(SysUserStatusEnum.NORMAL.getValue());
        // 唯一标识
        sysUser.setWxUid(openId);
        // 保存数据
        this.getBaseMapper().insert(sysUser);
        // 生成令牌
        LoginUser loginUser = new LoginUser();
        loginUser.setUser(sysUser);
        // 访问端
        loginUser.setPlatform(2);
        // 生成token
        String token = tokenService.createToken(loginUser);
        appUserLoginVo.setToken(token);
        appUserLoginVo.setUserId(sysUser.getUserId());
        appUserLoginVo.setUserType(sysUser.getUserType());
        // 是否绑定手机号
        if (StringUtils.isEmpty(sysUser.getPhoneNumber())) {
            appUserLoginVo.setIfBindPhone(Boolean.FALSE);
        }
        return AjaxResult.success("登录成功", appUserLoginVo);
    }

    @Override
    public AjaxResult<AppWxLoginVo> wxLogin(String code) {
        // 配置请求参数
        Map<String, String> param = new HashMap<>();
        param.put("appid", iSysCommonService.getById(1000002L).getCommonValue());
        param.put("secret", iSysCommonService.getById(1000003L).getCommonValue());
        param.put("js_code", code);
        param.put("grant_type", WechatUtils.WX_LOGIN_GRANT_TYPE);
        param.put("scope", "snsapi_userinfo");
        // 发送请求
        String wxResult = HttpUtils.sendGet(WechatUtils.WX_LOGIN_URL, param);
        log.info(wxResult);
        JSONObject jsonObject = JSONObject.parseObject(wxResult);
        // 获取参数返回的
        String session_key = jsonObject.get("session_key").toString();
        // 返回微信小程序openId
        String open_id = jsonObject.get("openid").toString();
        // 判断是否注册过
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper();
        // 微信
        lambdaQueryWrapper.eq(SysUser::getWxUid, open_id);
        List<SysUser> sysUserList = this.getBaseMapper().selectList(lambdaQueryWrapper);
        AppWxLoginVo appWxLoginVo = new AppWxLoginVo();
        if (CollectionUtils.isNotEmpty(sysUserList)) {
            AtomicReference<Boolean> statusNormal = new AtomicReference<>(false);
            AtomicReference<Boolean> statusStop = new AtomicReference<>(false);
            AtomicReference<Boolean> statusLogoff = new AtomicReference<>(false);
            AtomicReference<SysUser> sysUserAtomic = null;
            sysUserList.forEach(s -> {
                if (SysUserStatusEnum.NORMAL.getValue().equals(s.getStatus())) {
                    sysUserAtomic.set(s);
                    statusNormal.set(Boolean.TRUE);
                } else if (SysUserStatusEnum.STOP.getValue().equals(s.getStatus())) {
                    statusStop.set(Boolean.TRUE);
                } else if (SysUserStatusEnum.LOGOFF.getValue().equals(s.getStatus())) {
                    statusLogoff.set(Boolean.TRUE);
                }
            });
            if (!statusNormal.get() && !statusStop.get()) {
                appWxLoginVo.setFlag("1");//未注册
            } else if (!statusNormal.get() && statusStop.get()) {
                AssertUtils.isFalse(Boolean.TRUE, "该账号已被停用，请联系管理员");
            } else if (statusNormal.get()) {
                appWxLoginVo.setFlag("2");//注册过
            }
        } else {
            appWxLoginVo.setFlag("1");//未注册
        }
        // 封装返回小程序
        appWxLoginVo.setSession_key(session_key);
        appWxLoginVo.setOpen_id(open_id);
        if (jsonObject.get("unionid") != null) {
            String unionid = jsonObject.get("unionid").toString();
            appWxLoginVo.setUnionid(unionid);
        } else {
            appWxLoginVo.setUnionid("-1");
        }
        return AjaxResult.success(appWxLoginVo);
    }

    @Override
    public AjaxResult<String> getWxPhoneNumber(String code) {
        String wxPhoneNumber = WechatUtils.getWxPhoneNumber(iSysCommonService.getById(1000002L).getCommonValue(), iSysCommonService.getById(1000003L).getCommonValue(), code);
        return AjaxResult.success("获取手机号成功", wxPhoneNumber);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult<AppUserLoginVo> wxRegister(AppUserInfoEditBo appUserInfoEditBo) {
        AssertUtils.isTrue(StrUtil.isNotBlank(appUserInfoEditBo.getWxUid()), "账号信息获取失败，请退出重试！");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 根据返回的user实体类，判断用户是否是新用户，不是的话，更新最新登录时间，是的话，将用户信息存到数据库
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(SysUser::getWxUid, appUserInfoEditBo.getWxUid());
        List<SysUser> sysUserList = this.getBaseMapper().selectList(lambdaQueryWrapper);
        // 生成token
        LoginUser loginUser = new LoginUser();
        if (CollectionUtils.isNotEmpty(sysUserList)) {
            AtomicReference<Boolean> statusNormal = new AtomicReference<>(false);
            AtomicReference<Boolean> statusStop = new AtomicReference<>(false);
            AtomicReference<Boolean> statusLogoff = new AtomicReference<>(false);
            AtomicReference<SysUser> sysUserAtomic = new AtomicReference<SysUser>();
            sysUserList.forEach(s -> {
                if (SysUserStatusEnum.NORMAL.getValue().equals(s.getStatus())) {
                    sysUserAtomic.set(s);
                    statusNormal.set(Boolean.TRUE);
                } else if (SysUserStatusEnum.STOP.getValue().equals(s.getStatus())) {
                    statusStop.set(Boolean.TRUE);
                } else if (SysUserStatusEnum.LOGOFF.getValue().equals(s.getStatus())) {
                    statusLogoff.set(Boolean.TRUE);
                }
            });
            loginUser.setUser(sysUserAtomic.get());
            if (!statusNormal.get() && statusStop.get()) {
                AssertUtils.isFalse(Boolean.TRUE, "该账号已被停用，请联系管理员");
            }
            // 账号已注销
            if (!statusNormal.get() && !statusStop.get()) {
                // 判断是否在app登陆过  手机号是否有账号
                LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
                sysUserLambdaQueryWrapper.eq(SysUser::getPhoneNumber, appUserInfoEditBo.getPhoneNumber());
                List<SysUser> sysUserByPhoneNumberList = this.getBaseMapper().selectList(sysUserLambdaQueryWrapper);
                if (CollectionUtils.isNotEmpty(sysUserByPhoneNumberList)) {
                    AtomicReference<Boolean> statusNormal_1 = new AtomicReference<>(false);
                    AtomicReference<Boolean> statusStop_1 = new AtomicReference<>(false);
                    AtomicReference<Boolean> statusLogoff_1 = new AtomicReference<>(false);
                    AtomicReference<SysUser> sysUserAtomic_1 = new AtomicReference<SysUser>();
                    sysUserByPhoneNumberList.forEach(s -> {
                        if (SysUserStatusEnum.NORMAL.getValue().equals(s.getStatus())) {
                            sysUserAtomic_1.set(s);
                            statusNormal_1.set(Boolean.TRUE);
                        } else if (SysUserStatusEnum.STOP.getValue().equals(s.getStatus())) {
                            statusStop_1.set(Boolean.TRUE);
                        } else if (SysUserStatusEnum.LOGOFF.getValue().equals(s.getStatus())) {
                            statusLogoff_1.set(Boolean.TRUE);
                        }
                    });
                    if (!statusNormal_1.get() && statusStop_1.get()) {
                        AssertUtils.isFalse(Boolean.TRUE, "该账号已被停用，请联系管理员");
                    }
                    // 账号已注销
                    if (!statusNormal_1.get() && !statusStop_1.get()) {
                        // 没有则生成新账号
                        SysUser insertSysUser = new SysUser();
                        insertSysUser.setUserType(SysUserUserTypeEnum.GENERAL_USER.getValue());
                        insertSysUser.setUserName(appUserInfoEditBo.getPhoneNumber());
                        insertSysUser.setPhoneNumber(appUserInfoEditBo.getPhoneNumber());
                        // 默认密码
                        String initPassword = configService.selectConfigByKey("sys.user.initPassword");
                        insertSysUser.setPassword(SecurityUtils.encryptPassword(initPassword));
                        // 默认支付密码
                        String initPayPassword = configService.selectConfigByKey("sys.user.initPayPassword");
                        insertSysUser.setPayPassword(SecurityUtils.encryptPassword(initPayPassword));
                        baseMapper.insert(insertSysUser);
                        loginUser.setUser(insertSysUser);
                    }
                    if (statusNormal_1.get()) {
                        SysUser sysUserByPhoneNumber = sysUserAtomic_1.get();
                        // 有账号则绑定账号
                        Date date = new Date();
                        LambdaUpdateWrapper<SysUser> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                        lambdaUpdateWrapper.eq(SysUser::getUserId, sysUserByPhoneNumber.getUserId());
                        lambdaUpdateWrapper.set(SysUser::getWxUid, appUserInfoEditBo.getWxUid());
                        lambdaUpdateWrapper.set(SysUser::getUpdateTime, date);
                        this.getBaseMapper().update(null, lambdaUpdateWrapper);
                        sysUserByPhoneNumber.setWxUid(appUserInfoEditBo.getWxUid());
                        sysUserByPhoneNumber.setUpdateTime(date);
                        loginUser.setUser(sysUserByPhoneNumber);
                    }
                } else {
                    // 没有则生成新账号
                    SysUser insertSysUser = new SysUser();
                    insertSysUser.setUserType(SysUserUserTypeEnum.GENERAL_USER.getValue());
                    insertSysUser.setUserName(appUserInfoEditBo.getPhoneNumber());
                    insertSysUser.setPhoneNumber(appUserInfoEditBo.getPhoneNumber());
                    // 默认密码
                    String initPassword = configService.selectConfigByKey("sys.user.initPassword");
                    insertSysUser.setPassword(SecurityUtils.encryptPassword(initPassword));
                    // 默认支付密码
                    String initPayPassword = configService.selectConfigByKey("sys.user.initPayPassword");
                    insertSysUser.setPayPassword(SecurityUtils.encryptPassword(initPayPassword));
                    baseMapper.insert(insertSysUser);
                    loginUser.setUser(insertSysUser);
                }
            }
        } else {
            // 判断是否在app登陆过  手机号是否有账号
            LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysUserLambdaQueryWrapper.eq(SysUser::getPhoneNumber, appUserInfoEditBo.getPhoneNumber());
            List<SysUser> sysUserByPhoneNumberList = this.getBaseMapper().selectList(sysUserLambdaQueryWrapper);
            if (CollectionUtils.isNotEmpty(sysUserByPhoneNumberList)) {
                AtomicReference<Boolean> statusNormal_1 = new AtomicReference<>(false);
                AtomicReference<Boolean> statusStop_1 = new AtomicReference<>(false);
                AtomicReference<Boolean> statusLogoff_1 = new AtomicReference<>(false);
                AtomicReference<SysUser> sysUserAtomic_1 = new AtomicReference<SysUser>();
                sysUserByPhoneNumberList.forEach(s -> {
                    if (SysUserStatusEnum.NORMAL.getValue().equals(s.getStatus())) {
                        sysUserAtomic_1.set(s);
                        statusNormal_1.set(Boolean.TRUE);
                    } else if (SysUserStatusEnum.STOP.getValue().equals(s.getStatus())) {
                        statusStop_1.set(Boolean.TRUE);
                    } else if (SysUserStatusEnum.LOGOFF.getValue().equals(s.getStatus())) {
                        statusLogoff_1.set(Boolean.TRUE);
                    }
                });
                if (!statusNormal_1.get() && statusStop_1.get()) {
                    AssertUtils.isFalse(Boolean.TRUE, "该账号已被停用，请联系管理员");
                }
                // 账号已注销
                if (!statusNormal_1.get() && !statusStop_1.get()) {
                    // 没有则生成新账号
                    SysUser insertSysUser = new SysUser();
                    insertSysUser.setUserType(SysUserUserTypeEnum.GENERAL_USER.getValue());
                    insertSysUser.setUserName(appUserInfoEditBo.getPhoneNumber());
                    insertSysUser.setPhoneNumber(appUserInfoEditBo.getPhoneNumber());
                    // 默认密码
                    String initPassword = configService.selectConfigByKey("sys.user.initPassword");
                    insertSysUser.setPassword(SecurityUtils.encryptPassword(initPassword));
                    // 默认支付密码
                    String initPayPassword = configService.selectConfigByKey("sys.user.initPayPassword");
                    insertSysUser.setPayPassword(SecurityUtils.encryptPassword(initPayPassword));
                    baseMapper.insert(insertSysUser);
                    loginUser.setUser(insertSysUser);
                }
                if (statusNormal_1.get()) {
                    SysUser sysUserByPhoneNumber = sysUserAtomic_1.get();
                    // 有账号则绑定账号
                    Date date = new Date();
                    LambdaUpdateWrapper<SysUser> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                    lambdaUpdateWrapper.eq(SysUser::getUserId, sysUserByPhoneNumber.getUserId());
                    lambdaUpdateWrapper.set(SysUser::getWxUid, appUserInfoEditBo.getWxUid());
                    lambdaUpdateWrapper.set(SysUser::getUpdateTime, date);
                    this.getBaseMapper().update(null, lambdaUpdateWrapper);
                    sysUserByPhoneNumber.setWxUid(appUserInfoEditBo.getWxUid());
                    sysUserByPhoneNumber.setUpdateTime(date);
                    loginUser.setUser(sysUserByPhoneNumber);
                }
            } else {
                // 没有则生成新账号
                SysUser insertSysUser = new SysUser();
                insertSysUser.setUserType(SysUserUserTypeEnum.GENERAL_USER.getValue());
                insertSysUser.setUserName(appUserInfoEditBo.getPhoneNumber());
                insertSysUser.setPhoneNumber(appUserInfoEditBo.getPhoneNumber());
                // 默认密码
                String initPassword = configService.selectConfigByKey("sys.user.initPassword");
                insertSysUser.setPassword(SecurityUtils.encryptPassword(initPassword));
                // 默认支付密码
                String initPayPassword = configService.selectConfigByKey("sys.user.initPayPassword");
                insertSysUser.setPayPassword(SecurityUtils.encryptPassword(initPayPassword));
                baseMapper.insert(insertSysUser);
                loginUser.setUser(insertSysUser);
            }
        }
        loginUser.setPlatform(2);
        String token = tokenService.createToken(loginUser);
        AppUserLoginVo appUserLoginVo = new AppUserLoginVo();
        appUserLoginVo.setToken(token);
        appUserLoginVo.setIfBindPhone(Boolean.TRUE);
        appUserLoginVo.setUserType(loginUser.getUser().getUserType());
        appUserLoginVo.setUserId(loginUser.getUser().getUserId());
        return AjaxResult.success(appUserLoginVo);
    }

    @Override
    public AjaxResult<AppUserLoginVo> wxAppLogin(String wxOpenId, String accessToken) {
        // 判断是否注册过
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper();
        // 用户类型
        lambdaQueryWrapper.eq(SysUser::getUserType, SysUserUserTypeEnum.GENERAL_USER.getValue());
        // 微信
        lambdaQueryWrapper.eq(SysUser::getWxUid, wxOpenId);
        SysUser dbSysUser = baseMapper.selectOne(lambdaQueryWrapper);
        // 生成token
        LoginUser loginUser = new LoginUser();
        loginUser.setUser(dbSysUser);
        if (dbSysUser != null) {
            AssertUtils.isFalse(dbSysUser.getStatus() != null && SysUserStatusEnum.NORMAL.getValue().equals(dbSysUser.getStatus()), "账号已被禁用，请联系客服处理");
            String s = HttpClientUtil.doGet("https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + wxOpenId);
            AppWxUserInfoVo appWxUserInfoVo = JsonUtil.parseObject(s, AppWxUserInfoVo.class);
            if (appWxUserInfoVo != null && appWxUserInfoVo.getNickname() != null) {
                if (appWxUserInfoVo.getHeadimgurl() != null) {
                    dbSysUser.setAvatar(appWxUserInfoVo.getHeadimgurl());
                }
                dbSysUser.setSex(String.valueOf(appWxUserInfoVo.getSex()));
                if (appWxUserInfoVo.getNickname() != null) {
                    dbSysUser.setUserName(appWxUserInfoVo.getNickname().replaceAll("(\\d{3})\\d*([0-9a-zA-Z]{4})", "$1****$2"));
                }
            }
            LambdaUpdateWrapper<SysUser> sysUserLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            sysUserLambdaUpdateWrapper.eq(SysUser::getUserId, dbSysUser.getUserId());
            sysUserLambdaUpdateWrapper.set(SysUser::getWxUid, wxOpenId);
            sysUserLambdaUpdateWrapper.set(SysUser::getNickName, dbSysUser.getNickName());
            sysUserLambdaUpdateWrapper.set(SysUser::getAvatar, dbSysUser.getAvatar());
            sysUserLambdaUpdateWrapper.set(SysUser::getSex, dbSysUser.getSex());
            baseMapper.update(null, sysUserLambdaUpdateWrapper);

        } else {
            AssertUtils.isFalse(Boolean.TRUE, "请先绑定手机号账号");
        }
        loginUser.setPlatform(2);
        String token = tokenService.createToken(loginUser);
        AppUserLoginVo appUserLoginVo = new AppUserLoginVo();
        appUserLoginVo.setToken(token);
        appUserLoginVo.setIfBindPhone(Boolean.TRUE);
        appUserLoginVo.setUserType(loginUser.getUser().getUserType());
        appUserLoginVo.setUserId(loginUser.getUser().getUserId());
        return AjaxResult.success(appUserLoginVo);
    }

    @Override
    public AjaxResult<AppUserLoginVo> wxBindMobile(String phoneNumber, String veryCode, String wxOpenId, String accessToken) {
        // 验证手机号
        this.validateVeryCode(phoneNumber, veryCode);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = simpleDateFormat.format(new Date());
        // 判断是否注册过
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper();
        // 用户类型
        lambdaQueryWrapper.eq(SysUser::getUserType, SysUserUserTypeEnum.GENERAL_USER.getValue());
        lambdaQueryWrapper.in(SysUser::getStatus, SysUserStatusEnum.NORMAL.getValue(), SysUserStatusEnum.STOP.getValue());
        // 微信
        lambdaQueryWrapper.eq(SysUser::getPhoneNumber, phoneNumber);
        SysUser dbSysUser = baseMapper.selectOne(lambdaQueryWrapper);
        // 生成token
        LoginUser loginUser = new LoginUser();
        loginUser.setUser(dbSysUser);
        if (dbSysUser != null) {
            AssertUtils.isFalse(StringUtils.isNotEmpty(dbSysUser.getWxUid()), "当前手机号已经被其他微信绑定");
            //小程序登陆过
            dbSysUser.setWxUid(wxOpenId);
            String s = HttpClientUtil.doGet("https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + wxOpenId);
            AppWxUserInfoVo appWxUserInfoVo = JsonUtil.parseObject(s, AppWxUserInfoVo.class);
            if (appWxUserInfoVo != null && appWxUserInfoVo.getNickname() != null) {
                if (appWxUserInfoVo.getHeadimgurl() != null) {
                    dbSysUser.setAvatar(appWxUserInfoVo.getHeadimgurl());
                }
                dbSysUser.setSex(String.valueOf(appWxUserInfoVo.getSex()));
                if (appWxUserInfoVo.getNickname() != null) {
                    dbSysUser.setUserName(appWxUserInfoVo.getNickname().replaceAll("(\\d{3})\\d*([0-9a-zA-Z]{4})", "$1****$2"));
                }
            }
            LambdaUpdateWrapper<SysUser> sysUserLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            sysUserLambdaUpdateWrapper.eq(SysUser::getUserId, dbSysUser.getUserId());
            sysUserLambdaUpdateWrapper.set(SysUser::getWxUid, wxOpenId);
            sysUserLambdaUpdateWrapper.set(SysUser::getNickName, dbSysUser.getNickName());
            sysUserLambdaUpdateWrapper.set(SysUser::getAvatar, dbSysUser.getAvatar());
            sysUserLambdaUpdateWrapper.set(SysUser::getSex, dbSysUser.getSex());
            baseMapper.update(null, sysUserLambdaUpdateWrapper);
        } else {
            // 小程序没有登陆过
            dbSysUser = new SysUser();
            String s = HttpClientUtil.doGet("https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + wxOpenId);
            AppWxUserInfoVo appWxUserInfoVo = JsonUtil.parseObject(s, AppWxUserInfoVo.class);
            if (appWxUserInfoVo != null && appWxUserInfoVo.getNickname() != null) {
                if (appWxUserInfoVo.getHeadimgurl() != null) {
                    dbSysUser.setAvatar(appWxUserInfoVo.getHeadimgurl());
                }
                dbSysUser.setSex(String.valueOf(appWxUserInfoVo.getSex()));
                if (appWxUserInfoVo.getNickname() != null) {
                    dbSysUser.setUserName(appWxUserInfoVo.getNickname().replaceAll("(\\d{3})\\d*([0-9a-zA-Z]{4})", "$1****$2"));
                }
            }
            dbSysUser.setPhoneNumber(phoneNumber);
            dbSysUser.setUserType(SysUserUserTypeEnum.GENERAL_USER.getValue());
            dbSysUser.setWxUid(wxOpenId);
            baseMapper.insert(dbSysUser);
        }
        loginUser.setPlatform(2);
        String token = tokenService.createToken(loginUser);
        AppUserLoginVo appUserLoginVo = new AppUserLoginVo();
        appUserLoginVo.setToken(token);
        appUserLoginVo.setIfBindPhone(Boolean.TRUE);
        appUserLoginVo.setUserType(loginUser.getUser().getUserType());
        appUserLoginVo.setUserId(loginUser.getUser().getUserId());
        return AjaxResult.success(appUserLoginVo);
    }


    @Override
    public AjaxResult resetPassword(Integer resetType, Integer type, String originalPassword, String newPassword) {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        Long userId = loginUser.getUser().getUserId();
        String password = loginUser.getPassword();
        String payPassword = loginUser.getPayPassword();
        if (type == 1 && resetType == 1) {
            AssertUtils.isTrue(originalPassword.equals(newPassword), "两次密码输入不一样");
        } else if (type == 1 && resetType == 2) {
            AssertUtils.isTrue(SecurityUtils.matchesPassword(originalPassword, password), "旧密码不正确");
            AssertUtils.isFalse(SecurityUtils.matchesPassword(newPassword, password), "新密码不能与旧密码相同");
        } else if (type == 2 && resetType == 1) {
            AssertUtils.isTrue(originalPassword.equals(newPassword), "两次密码输入不一样");
        } else if (type == 2 && resetType == 1) {
            AssertUtils.isTrue(SecurityUtils.matchesPassword(originalPassword, payPassword), "旧密码不正确");
            AssertUtils.isFalse(SecurityUtils.matchesPassword(newPassword, payPassword), "新密码不能与旧密码相同");
        }
        // 加密
        String encryptionPwd = SecurityUtils.encryptPassword(newPassword);
        LambdaUpdateWrapper<SysUser> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(SysUser::getUserId, userId);
        lambdaUpdateWrapper.set(type == 1, SysUser::getPassword, encryptionPwd);
        lambdaUpdateWrapper.set(type == 2, SysUser::getPayPassword, encryptionPwd);
        int updateCount = iSysUserService.getBaseMapper().update(null, lambdaUpdateWrapper);
        if (updateCount > 0) {
            // 更新缓存用户密码
            if (type == 1) {
                loginUser.getUser().setPassword(encryptionPwd);
            } else if (type == 2) {
                loginUser.getUser().setPayPassword(encryptionPwd);
            }
            tokenService.setLoginUser(loginUser);
            return AjaxResult.success("重置密码成功");
        }
        return AjaxResult.success("重置密码失败");
    }

    @Override
    public AjaxResult forgetPassword(String phoneNumber, String veryCode, String newPassword) {
        // 验证手机号
        this.validateVeryCode(phoneNumber, veryCode);
        // 查询条件
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(SysUser::getPhoneNumber, phoneNumber);
        List<SysUser> sysUserList = this.getBaseMapper().selectList(lambdaQueryWrapper);
        AssertUtils.isTrue(CollectionUtils.isNotEmpty(sysUserList), "此手机号未注册");
        AtomicReference<Boolean> statusNormal = new AtomicReference<>(false);
        AtomicReference<Boolean> statusStop = new AtomicReference<>(false);
        AtomicReference<Boolean> statusLogoff = new AtomicReference<>(false);
        AtomicReference<SysUser> sysUserAtomic = new AtomicReference<>();
        sysUserList.forEach(s -> {
            if (SysUserStatusEnum.NORMAL.getValue().equals(s.getStatus())) {
                sysUserAtomic.set(s);
                statusNormal.set(Boolean.TRUE);
            } else if (SysUserStatusEnum.STOP.getValue().equals(s.getStatus())) {
                statusStop.set(Boolean.TRUE);
            } else if (SysUserStatusEnum.LOGOFF.getValue().equals(s.getStatus())) {
                statusLogoff.set(Boolean.TRUE);
            }
        });
        if (!statusNormal.get() && statusStop.get()) {
            AssertUtils.isFalse(Boolean.TRUE, "该账号已被停用，请联系管理员");
        }
        if (!statusNormal.get() && !statusStop.get()) {
            AssertUtils.isFalse(Boolean.TRUE, "该账号已被注销，请联系管理员");
        }
        SysUser sysUser = sysUserAtomic.get();
        // 加密
        String encryptionPwd = SecurityUtils.encryptPassword(newPassword);
        LambdaUpdateWrapper<SysUser> sysUserLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        sysUserLambdaUpdateWrapper.eq(SysUser::getUserId, sysUser.getUserId());
        sysUserLambdaUpdateWrapper.set(SysUser::getPassword, encryptionPwd);
        sysUserLambdaUpdateWrapper.set(SysUser::getUpdateTime, new Date());
        int upDateCount = iSysUserService.getBaseMapper().update(null, sysUserLambdaUpdateWrapper);
        if (upDateCount > 0) {
            return AjaxResult.success("修改密码成功");
        }
        return AjaxResult.success("修改密码失败");
    }

    @Override
    public AjaxResult veryCode(String phoneNumber, String veryType, String userType) {
        // 是否真实验证码 1:是 0:否
        SysCommon dbSysCommon = iSysCommonService.getById(1000032L);
        int code = 123456;
        if (dbSysCommon != null && "1".equals(dbSysCommon.getCommonValue())) {
            code = (int) ((Math.random() * 9 + 1) * 100000);
        } else {
            this.saveVeryCodeRedis(phoneNumber, code);
            return AjaxResult.success("验证码发送成功");
        }
        if (null == userType) {
            userType = SysUserUserTypeEnum.GENERAL_USER.getValue();
        }
        // 验证类型 1:注册 2:忘记密码 3:绑定手机号 4：验证码登录
        // 忘记密码 | 验证码登录
        if ("2".equals(veryType) || "4".equals(veryType)) {
            LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysUserLambdaQueryWrapper.eq(SysUser::getPhoneNumber, phoneNumber);
            sysUserLambdaQueryWrapper.eq(SysUser::getUserType, userType);
            List<SysUser> sysUserList = iSysUserService.getBaseMapper().selectList(sysUserLambdaQueryWrapper);
            AssertUtils.isTrue(CollectionUtils.isNotEmpty(sysUserList), "该手机号未注册");
            AtomicReference<Boolean> statusNormal = new AtomicReference<>(false);
            AtomicReference<Boolean> statusStop = new AtomicReference<>(false);
            AtomicReference<Boolean> statusLogoff = new AtomicReference<>(false);
            AtomicReference<SysUser> sysUserAtomic = new AtomicReference<>();
            sysUserList.forEach(s -> {
                if (SysUserStatusEnum.NORMAL.getValue().equals(s.getStatus())) {
                    sysUserAtomic.set(s);
                    statusNormal.set(Boolean.TRUE);
                } else if (SysUserStatusEnum.STOP.getValue().equals(s.getStatus())) {
                    statusStop.set(Boolean.TRUE);
                } else if (SysUserStatusEnum.LOGOFF.getValue().equals(s.getStatus())) {
                    statusLogoff.set(Boolean.TRUE);
                }
            });
            if (!statusNormal.get() && statusStop.get()) {
                AssertUtils.isFalse(Boolean.TRUE, "该账号已被停用，请联系管理员");
            }
            if (!statusNormal.get() && !statusStop.get()) {
                AssertUtils.isFalse(Boolean.TRUE, "该账号已被注销，请联系管理员");
            }
        } else if ("1".equals(veryType)) {
            LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysUserLambdaQueryWrapper.eq(SysUser::getPhoneNumber, phoneNumber);
            sysUserLambdaQueryWrapper.eq(SysUser::getUserType, userType);
            List<SysUser> sysUserList = iSysUserService.getBaseMapper().selectList(sysUserLambdaQueryWrapper);
            if (CollectionUtils.isNotEmpty(sysUserList)) {
                AtomicReference<Boolean> statusNormal = new AtomicReference<>(false);
                AtomicReference<Boolean> statusStop = new AtomicReference<>(false);
                AtomicReference<Boolean> statusLogoff = new AtomicReference<>(false);
                AtomicReference<SysUser> sysUserAtomic = new AtomicReference<>();
                sysUserList.forEach(s -> {
                    if (SysUserStatusEnum.NORMAL.getValue().equals(s.getStatus())) {
                        sysUserAtomic.set(s);
                        statusNormal.set(Boolean.TRUE);
                    } else if (SysUserStatusEnum.STOP.getValue().equals(s.getStatus())) {
                        statusStop.set(Boolean.TRUE);
                    } else if (SysUserStatusEnum.LOGOFF.getValue().equals(s.getStatus())) {
                        statusLogoff.set(Boolean.TRUE);
                    }
                });
                if ((!statusNormal.get() && statusStop.get()) || statusNormal.get()) {
                    AssertUtils.isFalse(Boolean.TRUE, "当前手机号已被其他账号绑定");
                }
            }
        } else if ("3".equals(veryType)) {
            boolean flag = false;
            try {
                Long userId = SecurityUtils.getUserId();
                SysUser dbSysUser = baseMapper.selectById(userId);
                if (dbSysUser != null && phoneNumber.equals(dbSysUser.getPhoneNumber())) {
                    flag = true;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysUserLambdaQueryWrapper.eq(SysUser::getPhoneNumber, phoneNumber);
            sysUserLambdaQueryWrapper.eq(SysUser::getUserType, userType);
            List<SysUser> sysUserList = iSysUserService.getBaseMapper().selectList(sysUserLambdaQueryWrapper);
            if (CollectionUtils.isNotEmpty(sysUserList)) {
                AtomicReference<Boolean> statusNormal = new AtomicReference<>(false);
                AtomicReference<Boolean> statusStop = new AtomicReference<>(false);
                AtomicReference<Boolean> statusLogoff = new AtomicReference<>(false);
                AtomicReference<SysUser> sysUserAtomic = new AtomicReference<>();
                sysUserList.forEach(s -> {
                    if (SysUserStatusEnum.NORMAL.getValue().equals(s.getStatus())) {
                        sysUserAtomic.set(s);
                        statusNormal.set(Boolean.TRUE);
                    } else if (SysUserStatusEnum.STOP.getValue().equals(s.getStatus())) {
                        statusStop.set(Boolean.TRUE);
                    } else if (SysUserStatusEnum.LOGOFF.getValue().equals(s.getStatus())) {
                        statusLogoff.set(Boolean.TRUE);
                    }
                });
                if ((!statusNormal.get() && statusStop.get() && !flag) || (statusNormal.get() && !flag)) {
                    AssertUtils.isFalse(Boolean.TRUE, "当前手机号已被其他账号绑定");
                }
            }
        } else {
            AssertUtils.isFalse(Boolean.TRUE, "验证类型不正确");
        }
        // 短信服务商（1华为云 2 腾讯云 3 阿里云 4短信宝）
        dbSysCommon = iSysCommonService.getById(1000018L);
        // 默认华为云
        if (dbSysCommon == null || "1".equals(dbSysCommon.getCommonValue())) {
            // 华为云
            return sendMsgHuaWei(phoneNumber, veryType, code);
        } else if ("2".equals(dbSysCommon.getCommonValue())) {
            // 腾讯云短信发送
            return sendMsgTencent(phoneNumber, veryType, code);
        } else if ("3".equals(dbSysCommon.getCommonValue())) {
            // 阿里云短信发送
            return sendMsgAlibaba(phoneNumber, veryType, code);
        } else {
            return sendMsgDXB(phoneNumber, veryType, code);
        }
    }

    /**
     * 验证手机号
     *
     * @param phoneNumber
     * @param veryCode
     */
    private void validateVeryCode(String phoneNumber, String veryCode) {
        // 验证手机号
        boolean checkPhone = PhoneUtils.isPhoneLegal(phoneNumber);
        AssertUtils.isTrue(checkPhone, "手机号格式不正确");
        String redisVeryCode = stringRedisTemplate.opsForValue().get(RedisConstants.SMS_AUTH_CODE + phoneNumber);
        AssertUtils.notBlank(redisVeryCode, "验证码已过期");
        AssertUtils.isTrue(veryCode.equals(redisVeryCode), "验证码不正确");
    }

    @Override
    public AjaxResult<Void> bindPhoneNumber(String newUserName, String veryCode, String password) {
        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysUserLambdaQueryWrapper.in(SysUser::getStatus, SysUserStatusEnum.NORMAL.getValue(), SysUserStatusEnum.STOP.getValue());
        // 手机号
        sysUserLambdaQueryWrapper.eq(SysUser::getPhoneNumber, newUserName);
        SysUser dbSysUser = iSysUserService.getBaseMapper().selectOne(sysUserLambdaQueryWrapper);
        AssertUtils.isNull(dbSysUser, "该账号已被绑定");
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        Long userId = loginUser.getUser().getUserId();
        // 更新
        LambdaUpdateWrapper<SysUser> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        boolean checkTel = PhoneUtils.isPhoneLegal(newUserName);
        AssertUtils.isTrue(checkTel, "手机号格式不对");
        String captcha = stringRedisTemplate.opsForValue().get(RedisConstants.SMS_AUTH_CODE + newUserName);
        AssertUtils.notNull(captcha, "手机验证码已过期");
        AssertUtils.isTrue(veryCode.equals(captcha), "手机验证码不正确");
        stringRedisTemplate.delete(RedisConstants.SMS_AUTH_CODE + newUserName);
        lambdaUpdateWrapper.eq(SysUser::getUserId, userId);
        lambdaUpdateWrapper.set(SysUser::getUserName, newUserName);
        lambdaUpdateWrapper.set(SysUser::getPhoneNumber, newUserName);
        lambdaUpdateWrapper.set(SysUser::getUpdateTime, new Date());
        String encryptPassword = SecurityUtils.encryptPassword(password);
        lambdaUpdateWrapper.set(SysUser::getPassword, encryptPassword);
        int updateCount = iSysUserService.getBaseMapper().update(null, lambdaUpdateWrapper);
        if (updateCount > 0) {
            // 更新缓存账号或者手机号
            loginUser.getUser().setUserName(newUserName);
            loginUser.getUser().setPhoneNumber(newUserName);
            loginUser.getUser().setPassword(encryptPassword);
            tokenService.setLoginUser(loginUser);
        }
        return updateCount > 0 ? AjaxResult.success("绑定成功") : AjaxResult.error("绑定失败");
    }

    @Override
    public AjaxResult<Void> bindNewPhoneNumber(String newUserName, String veryCode) {
        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 手机号
        sysUserLambdaQueryWrapper.eq(SysUser::getPhoneNumber, newUserName);
        List<SysUser> sysUserList = this.getBaseMapper().selectList(sysUserLambdaQueryWrapper);
        if (CollectionUtils.isNotEmpty(sysUserList)) {
            AssertUtils.isTrue(CollectionUtils.isNotEmpty(sysUserList), "此手机号未绑定");
            AtomicReference<Boolean> statusNormal = new AtomicReference<>(false);
            AtomicReference<Boolean> statusStop = new AtomicReference<>(false);
            AtomicReference<Boolean> statusLogoff = new AtomicReference<>(false);
            AtomicReference<SysUser> sysUserAtomic = new AtomicReference<>();
            sysUserList.forEach(s -> {
                if (SysUserStatusEnum.NORMAL.getValue().equals(s.getStatus())) {
                    sysUserAtomic.set(s);
                    statusNormal.set(Boolean.TRUE);
                } else if (SysUserStatusEnum.STOP.getValue().equals(s.getStatus())) {
                    statusStop.set(Boolean.TRUE);
                } else if (SysUserStatusEnum.LOGOFF.getValue().equals(s.getStatus())) {
                    statusLogoff.set(Boolean.TRUE);
                }
            });
            if ((!statusNormal.get() && statusStop.get()) || statusNormal.get()) {
                AssertUtils.isFalse(Boolean.TRUE, "该账号已被绑定");
            }
        }
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        Long userId = loginUser.getUser().getUserId();
        // 更新
        LambdaUpdateWrapper<SysUser> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        boolean checkTel = PhoneUtils.isPhoneLegal(newUserName);
        AssertUtils.isTrue(checkTel, "手机号格式不对");
        String captcha = stringRedisTemplate.opsForValue().get(RedisConstants.SMS_AUTH_CODE + newUserName);
        AssertUtils.notNull(captcha, "手机验证码已过期");
        AssertUtils.isTrue(veryCode.equals(captcha), "手机验证码不正确");
        stringRedisTemplate.delete(RedisConstants.SMS_AUTH_CODE + newUserName);
        lambdaUpdateWrapper.eq(SysUser::getUserId, userId);
        lambdaUpdateWrapper.set(SysUser::getUserName, newUserName);
        lambdaUpdateWrapper.set(SysUser::getPhoneNumber, newUserName);
        lambdaUpdateWrapper.set(SysUser::getUpdateTime, new Date());
        int updateCount = iSysUserService.getBaseMapper().update(null, lambdaUpdateWrapper);
        if (updateCount > 0) {
            // 更新缓存账号或者手机号
            loginUser.getUser().setUserName(newUserName);
            loginUser.getUser().setPhoneNumber(newUserName);
            tokenService.setLoginUser(loginUser);
        }
        return updateCount > 0 ? AjaxResult.success("绑定成功") : AjaxResult.error("绑定失败");
    }


    @Override
    public AjaxResult withdrawalBind(AppUserBindWxOrAliBo appUserBindWxOrAliBo) {
        Long userId = SecurityUtils.getUserId();
        LambdaUpdateWrapper<SysUser> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(SysUser::getUserId, userId);
        if ("1".equals(appUserBindWxOrAliBo.getPaymentType())) {
            lambdaUpdateWrapper.set(SysUser::getWxPayment, appUserBindWxOrAliBo.getPayment());
            lambdaUpdateWrapper.set(SysUser::getWxName, appUserBindWxOrAliBo.getName());
        } else {
            lambdaUpdateWrapper.set(SysUser::getAliPayment, appUserBindWxOrAliBo.getPayment());
            lambdaUpdateWrapper.set(SysUser::getAliName, appUserBindWxOrAliBo.getName());
        }
        lambdaUpdateWrapper.set(SysUser::getUpdateTime, new Date());
        Boolean ifUpdate = iSysUserService.update(null, lambdaUpdateWrapper);
        return ifUpdate ? AjaxResult.success("绑定成功") : AjaxResult.error("绑定失败");
    }

    @Override
    public String getCertifyId(MetaInfoParam metaInfoParam) {
        Long userId = SecurityUtils.getUserId();
        String metaInfo = JsonUtils.toJsonString(metaInfoParam);
        log.info("认证传参信息:" + metaInfo);
        // 实名认证AccessKeyID
        String AccessKeyID = iSysCommonService.getById(1000061L).getCommonValue();
        // 实名认证AccessKeySecret
        String AccessKeySecret = iSysCommonService.getById(1000062L).getCommonValue();
        // 实名认证SceneId
        String SceneId = iSysCommonService.getById(1000063L).getCommonValue();
        String certifyId = InitFaceVerify.getCertifyId(AccessKeyID, AccessKeySecret, Long.parseLong(SceneId), metaInfo, userId);
        return certifyId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int realAuth(RealNameParam realNameParam) {
        AssertUtils.notBlank(realNameParam.getCertifyId(), "证人ID不能为空");
        // 实名认证AccessKeyID
        String AccessKeyID = iSysCommonService.getById(1000061L).getCommonValue();
        // 实名认证AccessKeySecret
        String AccessKeySecret = iSysCommonService.getById(1000062L).getCommonValue();
        // 实名认证SceneId
        String SceneId = iSysCommonService.getById(1000063L).getCommonValue();
        MaterialInfo materialInfo = DescribeFaceVerify.getMaterialInfo(AccessKeyID, AccessKeySecret, Long.parseLong(SceneId), realNameParam.getCertifyId());
        // 身份信息
        Map<String, String> ocrIdCardInfo = materialInfo.getOcrIdCardInfo();
        System.out.println("身份信息=>>>" + JsonUtils.toJsonString(ocrIdCardInfo));
        String certNo = ocrIdCardInfo.get("certNo");
        String certName = ocrIdCardInfo.get("certName");
        Map<String, String> ocrPictureFront = materialInfo.getOcrPictureFront();
        System.out.println("图片信息=>>>" + JsonUtils.toJsonString(ocrPictureFront));
        // 正面地址
        String ossIdFaceUrl = ocrPictureFront.get("ossIdFaceUrl");
        String cardFront = ossIdFaceUrl;
        // 反面地址
        String ossIdNationalEmblemUrl = ocrPictureFront.get("ossIdNationalEmblemUrl");
        String cardBack = ossIdNationalEmblemUrl;
        Long userId = SecurityUtils.getUserId();
        LambdaUpdateWrapper<SysUser> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(SysUser::getUserId, userId);
        // lambdaUpdateWrapper.set(SysUser::getCardFront,cardFront);
        // lambdaUpdateWrapper.set(SysUser::getCardBack,cardBack);
        // lambdaUpdateWrapper.set(SysUser::getRealAuthStatus,1);
        return baseMapper.update(null, lambdaUpdateWrapper);
    }

    @Override
    public AjaxResult aliVerifyMobile(String accessCode, String phoneNumber) {
        Client client = null;
        VerifyMobileResponse verifyMobileResponse = new VerifyMobileResponse();
        try {
            //从数据库查询获取短信全局配置数据
            String accessKeyId = iSysCommonService.getById(1000015L).getCommonValue();
            String accessKeySecret = iSysCommonService.getById(1000015L).getCommonValue();
            if (StringUtils.isNoneEmpty(accessKeyId, accessKeySecret)) {
                client = createClient(accessKeyId, accessKeySecret);
                VerifyMobileRequest verifyMobileRequest = new VerifyMobileRequest();
                verifyMobileRequest.setAccessCode(accessCode);
                verifyMobileRequest.setPhoneNumber(phoneNumber);
                verifyMobileResponse = client.verifyMobile(verifyMobileRequest);
                if (!com.aliyun.teautil.Common.equalString(verifyMobileResponse.body.code, "OK")) {
                    log.info("错误信息:" + verifyMobileResponse.body.message + "");
                    return AjaxResult.error();
                }
                log.info("响应结果:" + verifyMobileResponse.body + "");
                return AjaxResult.success();
            } else {
                log.error("本机号码校验认证失败，获取系统配置短信秘钥信息为空");
                return AjaxResult.error();
            }
        } catch (Exception e) {
            log.error(verifyMobileResponse.body.getMessage());
            return AjaxResult.error();
        }
    }

    @Override
    public AjaxResult aliGetMobile(String accessToken) {
        //从数据库查询获取短信全局配置数据
        String accessKeyId = iSysCommonService.getById(1000041L).getCommonValue();
        String accessKeySecret = iSysCommonService.getById(1000042L).getCommonValue();
        if (StringUtils.isNoneEmpty(accessKeyId, accessKeySecret)) {
            com.aliyun.dypnsapi20170525.Client client = null;
            GetMobileRequest mobileRequest = new GetMobileRequest();
            mobileRequest.accessToken = accessToken;
            GetMobileResponse response = null;
            try {
                client = createClient(accessKeyId, accessKeySecret);
                ;
                response = client.getMobile(mobileRequest);
            } catch (Exception e) {
                log.error(response.body.getMessage());
                return AjaxResult.error();
            }
            if (!com.aliyun.teautil.Common.equalString(response.body.code, "OK")) {
                log.info("错误信息:" + response.body.message + "");
                return AjaxResult.error();
            }
            String phoneNumber = response.body.getGetMobileResultDTO().mobile;
            // 查询条件
            LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper();
            lambdaQueryWrapper.eq(SysUser::getPhoneNumber, phoneNumber);
            lambdaQueryWrapper.eq(SysUser::getUserType, SysUserUserTypeEnum.GENERAL_USER.getValue());
            lambdaQueryWrapper.in(SysUser::getStatus, SysUserStatusEnum.NORMAL.getValue(), SysUserStatusEnum.STOP.getValue());
            SysUser sysUser = this.getBaseMapper().selectOne(lambdaQueryWrapper);
            System.out.println(sysUser);
            if (ObjectUtil.isEmpty(sysUser)) {
                sysUser = new SysUser();
                //注册
                // 用户类型
                sysUser.setUserType(SysUserUserTypeEnum.GENERAL_USER.getValue());
                // 账号
                sysUser.setUserName(phoneNumber);
                //手机号
                sysUser.setPhoneNumber(phoneNumber);
                // 默认支付密码
                //String initPayPassword = configService.selectConfigByKey("sys.user.initPayPassword");
                //sysUser.setPayPassword(SecurityUtils.encryptPassword(initPayPassword));
                iSysUserService.getBaseMapper().insert(sysUser);
                // 导入用户 TODO 报错
                /*List<String> list = iTencentService.getImConfig();
                ImUtils.impUser(Long.parseLong(list.get(0)),list.get(1),list.get(2),sysUser.getUserId(),sysUser.getNickName(),sysUser.getAvatar());*/
            } else {
                if (sysUser.getStatus().equals(SysUserStatusEnum.STOP.getValue())) {
                    AssertUtils.isFalse(Boolean.TRUE, "该账号已被停用，请联系管理员");
                }
            }
            //更新用户设备标识
            //sysUser.setAlias(alias);
            iSysUserService.updateById(sysUser);
            // 生成token
            LoginUser loginUser = new LoginUser();
            loginUser.setUser(sysUser);
            // 访问端
            loginUser.setPlatform(2);
            String token = tokenService.createToken(loginUser);
            AppUserLoginVo appUserLoginVo = new AppUserLoginVo();
            appUserLoginVo.setUserId(sysUser.getUserId());
            appUserLoginVo.setIfBindPhone(Boolean.TRUE);
            appUserLoginVo.setUserType(sysUser.getUserType());
            appUserLoginVo.setToken(token);
            return AjaxResult.success("登录成功", appUserLoginVo);
        } else {
            log.error("阿里云号码认证（一键登录）失败，获取系统配置秘钥为空!");
            return AjaxResult.error();
        }
    }

    @Override
    public AjaxResult aliPayLogin(String code) {
        String appId = iSysCommonService.getById(1000104L).getCommonValue();
        String privateKey = iSysCommonService.getById(1000105L).getCommonValue();
        AlipaySystemOauthTokenResponse response = AliLoginUtils.getValidAuth(appId, privateKey, code);
        String uid = response.getUserId();
        return this.quickLogin(uid, SysUserLoginTypeEnum.ALIPAY_UID.getValue());
    }

    /**
     * 阿里云一键登录
     *
     * @param accessKeyId
     * @param accessKeySecret
     * @return
     * @throws Exception
     */
    public static com.aliyun.dypnsapi20170525.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
        Config config = new Config()
                .setAccessKeyId(accessKeyId)
                .setAccessKeySecret(accessKeySecret);
        return new com.aliyun.dypnsapi20170525.Client(config);
    }

    /**
     * 华为云短信
     *
     * @param phoneNumber
     * @param veryType
     * @param veryCode
     * @return
     */
    private AjaxResult sendMsgHuaWei(String phoneNumber, String veryType, int veryCode) {
        // 华为云签名通道号
        String sender = iSysCommonService.getById(1000021L).getCommonValue();
        // 收信人
        String receiver = "+86" + phoneNumber;
        // 短信签名
        String signatureName = iSysCommonService.getById(1000017L).getCommonValue();
        // 华为云模板号
        String templateId = iSysCommonService.getById(1000022L).getCommonValue();
        // 华为云短信accessKeyId
        String accessKeyId = iSysCommonService.getById(1000019L).getCommonValue();
        // 华为云短信accessSecret
        String accessSecret = iSysCommonService.getById(1000020L).getCommonValue();
        // 华为云短信接口地址
        String url = iSysCommonService.getById(1000023L).getCommonValue();
        // 请求Body,不携带签名名称时,signature请填null
        String body = this.buildRequestBody(sender, receiver, veryCode + "", signatureName, templateId);
        AssertUtils.notEmpty(body, "构建消息体失败！");
        // 请求Headers中的X-WSSE参数值
        String wsseHeader = buildWsseHeader(accessKeyId, accessSecret);
        AssertUtils.notEmpty(body, "构建wsse请求头失败！");

        CloseableHttpClient client;
        try {
            client = HttpClients.custom()
                    .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, (x509CertChain, authType) -> true).build())
                    .setSSLHostnameVerifier(new DefaultHostnameVerifier())
                    .build();
        } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
            throw new CustomException("初始化短信请求异常！" + e.getMessage());
        }

        try {
            HttpResponse response = client.execute(RequestBuilder.create("POST")
                    .setUri(url)
                    .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
                    .addHeader(HttpHeaders.AUTHORIZATION, "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"")
                    .addHeader("X-WSSE", wsseHeader)
                    .setEntity(new StringEntity(body)).build());
            String resultStr = EntityUtils.toString(response.getEntity());
            log.debug("短信发送结果：" + resultStr);
            Map<String, Object> result = JsonUtils.parseMap(resultStr);
            AssertUtils.notNull(result, "未获取短信发送结果！");
            boolean resultOk = "000000".equals(Objects.toString(result.get("code")));
            if (resultOk) {
                this.saveVeryCodeRedis(phoneNumber, veryCode);
                return AjaxResult.success("验证码发送成功");
            } else {
                return AjaxResult.error("验证码发送失败");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return AjaxResult.error("验证码发送失败");
    }

    /**
     * 构造请求Body体
     *
     * @param sender        华为云签名通道号
     * @param receiver      收信人手机号
     * @param templateParas 模板参数，一般为验证码
     * @param signatureName 短信签名
     * @param templateId    华为云模板号
     * @return 请求body
     */
    private String buildRequestBody(String sender, String receiver, String templateParas, String signatureName, String templateId) {
        List<NameValuePair> keyValues = new ArrayList<>();
        // 华为云签名通道号
        keyValues.add(new BasicNameValuePair("from", sender));
        keyValues.add(new BasicNameValuePair("to", receiver));
        // 华为云模板号
        keyValues.add(new BasicNameValuePair("templateId", templateId));
        if (StringUtils.isNotEmpty(templateParas)) {
            keyValues.add(new BasicNameValuePair("templateParas", String.format("[\"%s\"]", templateParas)));
        }
        if (StringUtils.isNotEmpty(signatureName)) {
            keyValues.add(new BasicNameValuePair("signature", signatureName));
        }
        return URLEncodedUtils.format(keyValues, StandardCharsets.UTF_8);
    }

    /**
     * 构造X-WSSE参数值
     *
     * @param appKey    appkey
     * @param appSecret appsecret
     * @return 请求头
     */
    private String buildWsseHeader(String appKey, String appSecret) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        String time = sdf.format(new Date());
        String nonce = UUID.randomUUID().toString().replace("-", "");
        byte[] passwordDigest = DigestUtils.sha256(nonce + time + appSecret);
        String hexDigest = Hex.encodeHexString(passwordDigest);
        String passwordDigestBase64Str = Base64.getEncoder().encodeToString(hexDigest.getBytes());
        return String.format("UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"", appKey, passwordDigestBase64Str, nonce, time);
    }

    /**
     * 腾讯短信
     *
     * @param phoneNumber
     * @param veryType
     * @param veryCode
     * @return
     */
    private AjaxResult sendMsgTencent(String phoneNumber, String veryType, int veryCode) {
        try {
            // 腾讯云短信clientId
            SysCommon three = iSysCommonService.getById(1000024L);
            String secretId = three.getCommonValue();
            // 腾讯云短信clientSecret
            SysCommon four = iSysCommonService.getById(1000025L);
            String secretKey = four.getCommonValue();
            // 腾讯云短信sdkAppId
            SysCommon five = iSysCommonService.getById(1000123L);
            String sdkAppId = five.getCommonValue();
            // 腾讯云短信region
            SysCommon seven = iSysCommonService.getById(1000125L);
            String templateId = seven.getCommonValue();
            // 腾讯云短信模板ID
            SysCommon eight = iSysCommonService.getById(1000124L);
            String region = eight.getCommonValue();
            // 短信签名
            SysCommon nine = iSysCommonService.getById(1000017L);
            String name = nine.getCommonValue();

            // 实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露，并威胁账号下所有资源的安全性。以下代码示例仅供参考，建议采用更安全的方式来使用密钥，请参见：https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential(secretId, secretKey);
            // 实例化一个http选项，可选的，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("sms.tencentcloudapi.com");
            // 实例化一个client选项，可选的，没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            SmsClient client = new SmsClient(cred, region, clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            SendSmsRequest req = new SendSmsRequest();
            String[] phoneNumberSet1 = {phoneNumber};
            req.setPhoneNumberSet(phoneNumberSet1);
            req.setSmsSdkAppId(sdkAppId);
            req.setSignName(name);
            req.setTemplateId(templateId);
            String[] templateParamSet1 = {veryCode + ""};
            req.setTemplateParamSet(templateParamSet1);
            // 返回的resp是一个SendSmsResponse的实例，与请求对象对应
            SendSmsResponse resp = client.SendSms(req);
            // 输出json格式的字符串回包
            System.out.println(SendSmsResponse.toJsonString(resp));
            if (resp.getSendStatusSet() != null && resp.getSendStatusSet().length > 0 && "Ok".equals(resp.getSendStatusSet()[0].getCode())) {
                this.saveVeryCodeRedis(phoneNumber, veryCode);
                return AjaxResult.success("验证码发送成功");
            } else {
                return AjaxResult.error("验证码发送失败");
            }
        } catch (Exception e) {
            // HTTP 响应码错误
            e.printStackTrace();
        }
        return AjaxResult.error("验证码发送失败");
    }

    /**
     * 阿里云短信
     *
     * @param phoneNumber
     * @param veryType
     * @param veryCode
     * @return
     */
    private AjaxResult sendMsgAlibaba(String phoneNumber, String veryType, int veryCode) {
        // 阿里云短信accessKeyId
        SysCommon three = iSysCommonService.getById(1000026L);
        String accessKeyId = three.getCommonValue();
        // 阿里云短信accessSecret
        SysCommon four = iSysCommonService.getById(1000027L);
        String accessSecret = four.getCommonValue();
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessSecret);
        IAcsClient client = new DefaultAcsClient(profile);
        SysCommon name = iSysCommonService.getById(1000017L);
        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", "cn-hangzhou");
        request.putQueryParameter("PhoneNumbers", phoneNumber);
        request.putQueryParameter("SignName", name.getCommonValue());
        String value = "";
        if ("1".equals(veryType)) {
            // 阿里云登陆或注册模板code（开启阿里云短信必须配置）
            value = iSysCommonService.getById(1000044L).getCommonValue();
        } else if ("2".equals(veryType)) {
            // 阿里云找回密码模板code（开启阿里云短信必须配置
            value = iSysCommonService.getById(1000045L).getCommonValue();
        } else if ("3".equals(veryType)) {
            // 阿里云绑定手机号模板code（开启阿里云短信必须配置）
            value = iSysCommonService.getById(1000046L).getCommonValue();
        }

        request.putQueryParameter("TemplateCode", value);
        request.putQueryParameter("TemplateParam", "{\"code\":\"" + veryCode + "\"}");
        try {
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
            String data = response.getData();
            JSONObject jsonObject = JSON.parseObject(data);
            if ("OK".equals(jsonObject.get("Code"))) {
                this.saveVeryCodeRedis(phoneNumber, veryCode);
                return AjaxResult.success("验证码发送成功");
            } else {
                if (jsonObject.get("Message").toString().contains("分钟")) {
                    return AjaxResult.error("短信发送过于频繁，请一分钟后再试！");
                } else if (jsonObject.get("Message").toString().contains("小时")) {
                    return AjaxResult.error("短信发送过于频繁，请一小时后再试！");
                } else if (jsonObject.get("Message").toString().contains("天")) {
                    return AjaxResult.error("短信发送过于频繁，请明天再试！");
                }
                log.info(jsonObject.get("Message").toString());
                return AjaxResult.error("验证码发送失败！");
            }
        } catch (ClientException | com.aliyuncs.exceptions.ClientException e) {
            e.printStackTrace();
        }
        return AjaxResult.error("验证码发送失败");
    }

    /**
     * 短信宝短信
     *
     * @param phoneNumber
     * @param veryType
     * @param veryCode
     * @return
     */
    private AjaxResult sendMsgDXB(String phoneNumber, String veryType, int veryCode) {
        SysCommon three = iSysCommonService.getById(1000028L);
        SysCommon four = iSysCommonService.getById(1000029L);
        // 短信签名
        SysCommon name = iSysCommonService.getById(1000017L);
        // 在短信宝注册的用户名
        String testUsername = three.getCommonValue();
        // 在短信宝注册的密码
        String testPassword = four.getCommonValue();
        String value = "";
        switch (veryType) {
            case "1":
                value = "【" + name.getCommonValue() + "】验证码: " + veryCode + "，此验证码可用于登录或注册，5分钟内有效，如非您本人操作，可忽略本条消息";
                break;
            case "2":
                value = "【" + name.getCommonValue() + "】验证码: " + veryCode + "，您正在执行找回密码操作，5分钟内有效，如非您本人操作，可忽略本条消息";
                break;
            case "3":
                value = "【" + name.getCommonValue() + "】验证码: " + veryCode + "，您正在执行绑定手机号操作，5分钟内有效，如非您本人操作，可忽略本条消息";
                break;
            default:
                value = "【" + name.getCommonValue() + "】验证码: " + veryCode + "，此验证码可用于登录或注册，5分钟内有效，如非您本人操作，可忽略本条消息";
                break;
        }
        StringBuilder httpArg = new StringBuilder();
        httpArg.append("u=").append(testUsername).append("&");
        httpArg.append("p=").append(MD5Utils.md5s(testPassword)).append("&");
        httpArg.append("m=").append(phoneNumber).append("&");
        httpArg.append("c=").append(MD5Utils.encodeUrlString(value, "UTF-8"));
        String result = MD5Utils.request("https://api.smsbao.com/sms", httpArg.toString());
        log.error("短信包返回值：" + result);
        if ("0".equals(result)) {
            this.saveVeryCodeRedis(phoneNumber, veryCode);
            return AjaxResult.success("验证码发送成功");
        } else {
            if ("30".equals(result)) {
                return AjaxResult.error("错误密码");
            } else if ("40".equals(result)) {
                return AjaxResult.error("账号不存在");
            } else if ("41".equals(result)) {
                return AjaxResult.error("余额不足");
            } else if ("43".equals(result)) {
                return AjaxResult.error("IP地址限制");
            } else if ("50".equals(result)) {
                return AjaxResult.error("内容含有敏感词");
            } else if ("51".equals(result)) {
                return AjaxResult.error("手机号码不正确");
            }
        }
        return AjaxResult.error("验证码发送失败");
    }

    /**
     * 验证码缓存
     *
     * @param phoneNumber
     * @param veryCode
     */
    private void saveVeryCodeRedis(String phoneNumber, int veryCode) {
        // 获取过期时间
        String smsExpireMinuteStr = redisTemplate.opsForValue().get(RedisConstants.SMS_EXPIRE_MINUTE);
        if (StringUtils.isBlank(smsExpireMinuteStr)) {
            smsExpireMinuteStr = Constants.SMS_EXPIRE_MINUTE + "";
        }
        smsExpireMinuteStr = smsExpireMinuteStr.replaceAll("\"", "");
        int smsExpireMinute = Integer.parseInt(smsExpireMinuteStr, 8);
        // 保存验证码
        redisTemplate.opsForValue().set(RedisConstants.SMS_AUTH_CODE + phoneNumber, veryCode + "", smsExpireMinute, TimeUnit.MINUTES);
    }
}
